package io.alterac.blurkit;

import com.enrique.stackblur.StackBlurManager;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.Image;
import ohos.agp.components.StackLayout;
import ohos.agp.components.Text;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.utils.RectFloat;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.ScaleMode;
import ohos.media.image.common.Size;

/**
 * 模糊了其背后的所有内容。
 * 自动创建父级内容的位图，
 * 并找到其与顶级父级的相对位置以正确绘制，而不管布局在何处
 *
 * @since 2021-04-06
 */
public class BlurLayout extends DependentLayout implements Component.DrawTask {
    private static final float NUM_025 = 0.25f;
    private static final int NUM_60 = 60;
    private static final int NUM_2 = 2;
    private static final int NUM_100 = 100;
    private static float ambiguity = NUM_025;
    float potionY = 0;
    PixelMap blurPixelMap;
    private PixelMap pixelMap2;
    private PixelMapHolder pixelMapHolder;
    private Paint paint2 = null;
    private int blkCornerRadius = 0;

    /**
     * 构造
     *
     * @param context 上下文
     */
    public BlurLayout(Context context) {
        super(context, null);
    }

    /**
     * 构造
     *
     * @param context 上下文
     * @param attrSet attrSet
     */
    public BlurLayout(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    /**
     * 构造
     *
     * @param context 上下文
     * @param attrSet attrSet
     * @param styleName styleName
     */
    public BlurLayout(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        initTypeValue(attrSet);
        initView();
    }

    /**
     * 初始化属性
     *
     * @param attrSet 自定义属性
     */
    private void initTypeValue(AttrSet attrSet) {
        ambiguity = getAttrSetFloat(attrSet, "blk_downscaleFactor", NUM_025);
        blkCornerRadius = getAttrSetInt(attrSet, "blk_cornerRadius", 0);
    }

    private void initView() {
        setClipEnabled(true);
        setAlpha(0);
        addDrawTask(this::onDraw);
    }

    public void setY(float potionY2) {
        this.potionY = potionY2;
    }

    @Override
    public void invalidate() {
        super.invalidate();
        addDrawTask(this::onDraw);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        int left = component.getLeft();
        float top = potionY;
        int right = component.getRight();
        double bottom = (double)top + (double)component.getHeight();
        RectFloat rectFloat = new RectFloat(left, top, right, (float) bottom);
        StackLayout stackLayout = (StackLayout) component.getComponentParent();
        if (pixelMap2 == null) {
            Image image = (Image) stackLayout.getComponentAt(0);
            image.setScaleMode(Image.ScaleMode.CLIP_CENTER);
            if (pixelMapHolder == null) {
                pixelMapHolder = image.getPixelMapHolder();
            }
            PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
            initializationOptions.editable = true;
            initializationOptions.scaleMode = ScaleMode.CENTER_CROP;
            initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
            Size size = new Size(image.getWidth(), image.getHeight());
            initializationOptions.size = size;
            pixelMap2 = PixelMap.create(pixelMapHolder.getPixelMap(), initializationOptions);
            StackBlurManager stackBlurManager = new StackBlurManager(pixelMap2);
            /**
             * 方法里面设置模糊度
             */
            blurPixelMap = stackBlurManager.process((int) (ambiguity * NUM_100));
        }

        RectFloat rect3 = new RectFloat(0, 0, component.getWidth(), component.getHeight());
        canvas.drawPixelMapHolderRoundRectShape(new PixelMapHolder(blurPixelMap),
                rectFloat, rect3, blkCornerRadius, blkCornerRadius);
        DependentLayout stackLayout1 = (DependentLayout) component;
        for (int ii = 0; ii < stackLayout1.getChildCount(); ii++) {
            if (stackLayout1.getComponentAt(ii) instanceof Text) {
                Text text = (Text) stackLayout1.getComponentAt(ii);
                text.setVisibility(INVISIBLE);
                if (paint2 == null) {
                    paint2 = new Paint();
                }
                paint2.setColor(text.getTextColor());
                paint2.setTextSize(text.getTextSize());
                paint2.setStyle(Paint.Style.FILLANDSTROKE_STYLE);
                paint2.setTextAlign(TextAlignment.CENTER);
                canvas.drawText(paint2, text.getText(), (float) (component.getWidth() / (double) NUM_2),
                        (float) (component.getHeight() / (double) NUM_2));
            }
        }
    }

    private float getAttrSetFloat(AttrSet attrs, String key, float def) {
        if (attrs.getAttr(key).isPresent()) {
            return attrs.getAttr(key).get().getFloatValue();
        } else {
            return def;
        }
    }

    private int getAttrSetInt(AttrSet attrs, String key, int def) {
        if (attrs.getAttr(key).isPresent()) {
            return attrs.getAttr(key).get().getIntegerValue();
        } else {
            return def;
        }
    }
}
